#include "QwtBasicXYchart.h"
#include <QVector>
#include <QMessageBox>
#include <cstdlib>
#include <time.h>
#include <qwt/qwt_symbol.h>

namespace LightChart
{
    void QwtBasicXYchart::draw() {}
    void QwtBasicXYchart::preparePlot(QwtPlot* plot, ChartType chartType)
    {
	/*plot settings */
	plot->setAutoReplot(true);
	plot->setTitle(chart.get_title().c_str());
	QBrush background(chart.getBgColor());
	plot->setCanvasBackground(background);
	plot->setFixedSize(chart.getWindowWidth(),chart.getWindowHeight());
	const std::vector<Axis*>& axisptr = chart.get_axes();
	plot->setAxisTitle(QwtPlot::xBottom,QString(axisptr[0]->get_label().c_str()));
	plot->setAxisTitle(QwtPlot::yLeft,QString(axisptr[1]->get_label().c_str()));
	double min, max;
	if((min = axisptr[0]->get_min()) != (max = axisptr[0]->get_max()))
	    plot->setAxisScale(QwtPlot::xBottom,min,max,axisptr[0]->get_tics());
	if((min = axisptr[1]->get_min()) != (max = axisptr[1]->get_max()))
	    plot->setAxisScale(QwtPlot::yLeft,min,max,axisptr[1]->get_tics());

	/* grid settings */
	QwtPlotGrid* grid = new QwtPlotGrid();
	grid->attach(plot);

	/* curve settings */
	QVector<QwtPlotCurve*> curves;
	QVector<QPen> colors;
	colors.push_back(QPen(Qt::red));
	colors.push_back(QPen(Qt::blue));
	colors.push_back(QPen(Qt::green));
	srand(time(NULL));
	try
	{
	    std::map<Axis*, std::vector<Series*> >& axes = Storage::get_instance().charts[&chart];
	    auto itx = axes.begin();
	    auto ity = ++axes.begin();
	    if(itx == axes.end() || ity == axes.end()) throw std::logic_error("Internal error: too few axes.");
	    std::vector<Series*>& series_x = itx->second;
	    std::vector<Series*>& series_y = ity->second;
	    if(series_x.size() != series_y.size()) throw std::logic_error("Number of data series assigned to x-axis is not not equal to the number of "
									  "series assigned to y-axis. Chart will not be plotted. If you want to plot "
									  "multiple curves on one canvas you need to assign the same (or different) "
									  "data series to x-axis. If you assign different series to x-axis they will "
									  "be merged. Please assign missing series and try again.");
	    for(unsigned int i = 0; i < series_x.size(); ++i)
	    {
		QwtPlotCurve* curve = new QwtPlotCurve();
		if(i >= 3) colors.push_back(QPen(QColor(rand() % 256, rand() % 256, rand() % 256)));
		curve->setPen(colors[i]);
		curve->setRenderHint(QwtPlotCurve::RenderAntialiased);
		if(chartType == QwtBasicXYchart::SCATTER_CHART)
		{
		    curve->setStyle(QwtPlotCurve::NoCurve);
		    QwtSymbol*  symbol = new QwtSymbol(QwtSymbol::XCross);
		    symbol->setSize(7,7);
		    symbol->setColor(colors[i].color());
		    curve->setSymbol(symbol);
		}

		Series* serie_x = series_x[i];
		Series* serie_y = series_y[i];

		if(serie_x->get_type() == S_TEXT || serie_y->get_type() == S_TEXT) throw std::logic_error("One or more assigned data series"
		    " contains text instead of numbers. This data serie's type is not supported. The chart will not be plotted. Please assign"
		    " data series that contains numbers.");
		if(serie_x->get_type() == UNKNOWN || serie_y->get_type() == UNKNOWN) throw std::logic_error("One or more assigned data series"
		    " contains unknown data type. The chart will not be plotted. Please assign data series that contains numbers.");

		std::vector<double>& tmpx = serie_x->get_double_vector();
		std::vector<double>& tmpy = serie_y->get_double_vector();
		curve->setSamples(QVector<double>::fromStdVector(tmpx),QVector<double>::fromStdVector(tmpy));
		curves.push_back(curve);
	    }
	}
	catch(const std::logic_error& e)
	{
	    QMessageBox::critical(0,"Error occured",e.what());
	}

	for(int i = 0; i < curves.size(); ++i) curves[i]->attach(plot);
	plot->updateLayout();
	plot->replot();
    }
}

